/**
 * \class CHashedFileTransfer
 * \brief This is a file transfer class in a broadcast way.
 * \version 0.3.2
 *
 * \author Woo-Hyun Kim (woorung@nhncorp.com, woorung@gmail.com)
 * \author http://blog.naver.com/wisereign .
 *
 * \date 2008/6/18
 */
#include "CHashedFileTransfer.h"
//-----------------------------------------------------------------
CHashedFileTransfer::CHashedFileTransfer(char *host, int port) 
{
	discovery_host = host;
	discovery_port = port;
}
//-----------------------------------------------------------------
CHashedFileTransfer::~CHashedFileTransfer() 
{
}
//-----------------------------------------------------------------
int CHashedFileTransfer::lookup(char *key, CServiceInfo &found_file_service)
{
	CChord *chord = new CChord((char *)discovery_host.c_str(), discovery_port);
	//chord->configure(CUBE_SERVICE_SPACE);
	CDHTKey *nodeip_key = new CNodeIPKey();
	chord->configure(CUBE_SERVICE_SPACE, nodeip_key);
	string space_key = key;
	found_file_service = chord->lookup((char *)space_key.c_str());

#ifdef DEBUG
	cout << "####################################################" << endl;
	cout << "found file key = " << key << " on " << found_file_service.getIP() << ":" << found_file_service.getPort() << endl;
	cout << "####################################################" << endl;
#endif

	delete nodeip_key;
	delete chord;
}
//-----------------------------------------------------------------
int CHashedFileTransfer::put(char *file) 
{
	return put(file, NULL);
}
//-----------------------------------------------------------------
int CHashedFileTransfer::put(char *file, char *repository_path) 
{
	string target_file = "";
	string full_path_file = file;

	// in order to hash key, extract only file name
	// -----------------------------------------------
	string::size_type pos = full_path_file.rfind("/");
	if(pos==string::npos) target_file = full_path_file;
	else target_file = full_path_file.substr(pos+1);
	// -----------------------------------------------

	CServiceInfo found_file_service;

	// DHT-based put
	lookup((char *)target_file.c_str(), found_file_service);

	return put(found_file_service.getIP(), found_file_service.getPort(), file, repository_path);
}
//-----------------------------------------------------------------
int CHashedFileTransfer::put(char *host, int port, char *file) 
{
	return put(host, port, file, NULL);
}
//-----------------------------------------------------------------
int CHashedFileTransfer::put(char *host, int port, char *file, char *repository_path) 
{
	CFileProxy *file_proxy = new CFileProxy(host, port);

	if(repository_path!=NULL) file_proxy->repository(repository_path);

	int status = file_proxy->put(file);
	if(status<1) cerr << "cannot put " << file << " to " << host << ":" << port << endl;

	delete file_proxy;

	return status;
}
//-----------------------------------------------------------------
int CHashedFileTransfer::get(char *file) 
{
	return get(file, NULL);
}
//-----------------------------------------------------------------
int CHashedFileTransfer::get(char *file, char *repository_path) 
{
	CServiceInfo found_file_service;

	// DHT-based get
	lookup(file, found_file_service);

	return get(found_file_service.getIP(), found_file_service.getPort(), file, repository_path);
}
//-----------------------------------------------------------------
int CHashedFileTransfer::get(char *host, int port, char *file) 
{
	return get(host, port, file, NULL);
}
//-----------------------------------------------------------------
int CHashedFileTransfer::get(char *host, int port, char *file, char *repository_path) 
{
	CFileProxy *file_proxy = new CFileProxy(host, port);

	if(repository_path!=NULL) file_proxy->repository(repository_path);

	int status = file_proxy->get(file);
	if(status<1) cerr << "cannot get " << file << " to " << host << ":" << port << endl;

	delete file_proxy;

	return status;
}
//-----------------------------------------------------------------
int CHashedFileTransfer::tget(char *file, char *tkey) 
{
	return tget(file, tkey, NULL);
}
//-----------------------------------------------------------------
int CHashedFileTransfer::tget(char *file, char *tkey, char *repository_path) 
{
	CServiceInfo found_file_service;

	string real_file_for_lookup = file;
	string::size_type pos = real_file_for_lookup.rfind(tkey);
	if(pos==string::npos) ;
	else real_file_for_lookup.erase(pos, strlen(tkey)); // erase trivial key from file

	// DHT-based get
	lookup((char *)real_file_for_lookup.c_str(), found_file_service);

	return get(found_file_service.getIP(), found_file_service.getPort(), file, repository_path);
}
//-----------------------------------------------------------------
